package com.example.xzs.admin.userlogin.service.impl;


import com.alibaba.fastjson.JSON;
import com.example.xzs.admin.userlogin.dao.repository.IUserRepository;
import com.example.xzs.admin.userlogin.enumerator.ServiceCode;
import com.example.xzs.admin.userlogin.ex.ServiceException;
import com.example.xzs.admin.userlogin.pojo.authentication.CurrentPrincipal;
import com.example.xzs.admin.userlogin.pojo.entiy.User;
import com.example.xzs.admin.userlogin.pojo.param.UserLogin;
import com.example.xzs.admin.userlogin.pojo.param.UserRegistration;
import com.example.xzs.admin.userlogin.pojo.vo.UserLoginInfoVo;
import com.example.xzs.admin.userlogin.security.UserLogDetails;
import com.example.xzs.admin.userlogin.service.IUserService;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class UserServiceImpl  implements IUserService {
    @Autowired
    private IUserRepository userRepository;
    @Autowired
    private PasswordEncoder encoder; // 加密
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void insertUserData(UserRegistration registration) {
        UserLoginInfoVo userLoginInfoVo=userRepository.selectUser(registration.getUsername());
           if(userLoginInfoVo!=null){
               String message="注册失败，用户已存在！";
                throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
           }
           User user=new User();
           BeanUtils.copyProperties(registration,user);
           user.setEnable(1);
           user.setAdmin(0);

           //密码加密
           user.setPassword(encoder.encode(user.getPassword()));
           userRepository.insert(user);

    }

    @Override
    public String login(UserLogin userLogin, String remoteAddr, String userAgent) {

        Authentication authentication=new UsernamePasswordAuthenticationToken(
                userLogin.getUsername(),userLogin.getPassword());
        Authentication authenticationResult=authenticationManager.authenticate(authentication);
        Object principal=authenticationResult.getPrincipal();
        UserLogDetails userLogDetails= (UserLogDetails) principal;
        String username=userLogDetails.getUsername();
        Long id=userLogDetails.getId();
        Collection<GrantedAuthority> authorities=userLogDetails.getAuthorities();
        log.debug("权限:"+authorities);
        String authoritiesJsonString= JSON.toJSONString(authorities);
        String  secretKey="k4^&32flj5Ss(Jf&*(5%DK3da";  //私有钥匙
        Date date=new Date(System.currentTimeMillis()+30L*24*60*60*1000); //保持的时间
        Map<String,Object> map=new HashMap<>();
        map.put("id",id);
        map.put("username",username);
        map.put("remoteAddr",remoteAddr);
        map.put("userAgent",userAgent);
        map.put("admin",authoritiesJsonString);

        String jwt= Jwts.builder()//创建JWT的构建器
                .setHeaderParam("alg","HS256")//设计头部参数算法
                .setHeaderParam("typ","JWT")//设置头部参数为JWT，表示为JSON Web Token
                .setClaims(map)//主体部分.里面放的map键值对信息的映射，id 9827  用户名 root  也可以跟加入其他的
                .setExpiration(date)//设置保持的时间
                .signWith(SignatureAlgorithm.HS256,secretKey)//利用ES256算法对JWT进行签名，也就是生成加密后的签名
                .compact();//构成最终的JWT字符串
        return jwt;
        //完成响应

    }

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response) {

        Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
        log.debug("开始处理【退出登录】的业务，参数：{}"+ authentication);
        if (authentication==null) {
            String message = "操作失败，用户数据有误！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }

        SecurityContextLogoutHandler logoutHandler=new SecurityContextLogoutHandler();
         logoutHandler.logout(request,response,authentication);


    }
}























